home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 June: Reference Library / Dev.CD Jun 99 RL Disk 1.toast / Technical Documentation / Macintosh Technotes and Q&As / technotes / tn / tn_1076.cw < prev    next >
Encoding:
Text File  |  1998-04-25  |  82.1 KB  |  981 lines  |  [TEXT/R*ch]

  1. ˜BOBO·u4dHZHZHZ‹
  2. ·vPÿÿH·v\HZ.l.~.Δ.¢.´.Æ.Ô€=≈(=Sπ=SÌ=mè=mü=WL=møuí ÿÿ·u`ÿ-Zÿÿÿ Tom MaremaaxHHÚ(ÿáÿáùEG(üHHØ(d'`Δÿÿ·ˇ°∫l;`/À·9j·vh·uÀ´´·sÄ··À·ÿfl·¡À¶Ö@ ·vd4°ÿÿÿÿÿÿÿÿ&S†DSETp…ãŸ|„H*IÉ·yÌ·yà·y≥·yÄ·t¬°F·v;ı°F·vΔ/D
  3. 0°F·v°/9$°F·t5EA°F·v˛>F%—°F·sì5A,µ°F·v€4A5⁄°F·t2>?ŰF·t40CI·°F·v´0F    Sì°F·s˘3=
  4. ]°F·sô0F g°F·t≥C kÿ°F·s‰/;
  5. uï°F·sÀ“xn°F·s¬;E≥°F·t ?F∫≈°F·tl;CŸB°F·s|&ÀH’  (`,a,q,∑,˜¸˘,Z,[,ı,ƒ,ƒ, ,(,),c,d,e¸Œ,‚,    Ó,    Ô,
  6. å,
  7. æ¸
  8. ç¸ , , ‚, „,m,n,o,√,≈,4,5,µ,·È›È5ÈjÈ…ÈflÈıÈ5Ȁȥ,, ,!,",#,$,A,B,•,™,(,),*,?,@,¥,œÍ·ÍÉÍÙÍêÍüÍ$ÍOÍeÍyÍ®ÍßÍÍ.ÍJÍrÑsÑ Ñ!Í(ÍRÍ—ÍÁÍôÑ÷ÑøÑ?Í@ÍAÍZÍΔÍ´ÍçÍÍAÍtÍ¥ÍÓÍ Í FÍ lÍ ˙Í ±Ñ ”Í “Í ÏÍ!Í!+Í!\Í!„Í!ÁÍ!ìÍ"!Í"?Ñ"@Ñ"AÑ"¶Ñ"·Ñ#.Ñ#/Í#6Í#fÍ#„Í#ÓÍ$Í$EÍ$•Í$∞Í$≥Í$ÈÍ$ÉÍ$fiÍ$ôÍ%    Í%'Í%FÍ%eÍ%•Í%™Í%≠Í%∞Í%≥Í%∑Í%∫Í%ΩÍ%√Í%≈Í%…Í%—Í%ëÍ&'Í&]Í&™Í&¥Í&ãÍ'Í'IÍ'∫Í'ÃÍ'öÍ(&Í(LÍ(dÍ(eÍ(™Í(ˇÍ(°Í(ïÍ)/Í)ZÍ)…Í)¨Ñ)©Ñ)ÖÑ)◊Ñ+ÇÑ+ÈÑ,e0,f0,¢Ñ,£Ñ,€G,œG,¨G,ªG,¬,–,®,¯,°,±,”,“,´,µÑ.lÑ.mÑ.nÑ.∂Ñ.ΔÑ/EÑ/FÍ/|Í/‚Í/ªÍ/ÀÍ/ãÍ0Í03Ñ04Ñ0‹Ñ0ÑÑ1ÒÑ1ÓÑ1óÑ1ôÑ3ÏÑ3‹Í4Í4Í4JÍ4}Í4’Í4æÍ4êÍ5Í5GÍ5vÍ5}Í5⁄Ñ5∂Ñ5ΔÑ5¯Ñ5°Ñ8Ñ8Ñ8QÑ8RÍ8≠Í8¨Í8ÎÍ9Í9@Í9iÍ9€Í9ËÍ9øÍ:*Í:+Ñ:,Ñ<|Ñ<}Ñ>
  9. Ñ> Ñ?ÃÑ?ÄÑ?ÅÑ@∞Ñ@≥ÑAFÑAGÑB˝ÑB˛ÑCÒÑCÓÑCñÑCòÑE/ÑE0ÑFxÑFyÑGPÑGQÑILÑIMÑI·ÑI¸ÑI’ÑIÍÑIÎÑLOÑLPÑN›ÑNñÑNòÑQQÑQRÑR¨ÑR©ÑRªÑRÉÑRÊÑSëÑSìÍTÍTVÍTΔÍTÎÍTÿÍUÑUgÑUhÍUˇÍU”ÍUÉÍUfiÍVÍV+ÍV=ÍVPÍVQÑV£ÑV€ÑXÑXÑZÑZÑ[ØÑ[ÙÑ[ÚÑ[øÑ[ùÑ\ÿÑ]Ñ]Ñ^Ñ^•Ñ_„Ñ_‰Ñ`œÑ`§Ña·Ña¸Ña’Ña◊ÑaØÑb÷ÑbøÑd%Ñd&ÑdÚÑdÛÑdÜÑeÑeÑhOÑhPÑiî0iï0j-Ñj.+j0áj1Ñl√Ñl≈Ñn\Ñn]ÑoÑoÑpÅÑpÆÑqˆÑq˜Ñq˘Ñq€Ñq¥Ñs∑Ñs∫ÑuìÑuíÑuîÑuïÑvÑvÑw|Ñw}ÑwòÑwóÑxméxnéx⁄éx∂Ñy]Ñy^ÑynÑyoÍy¬Íy–Íy´Íy†ÍzÍzKÍz}Íz•Íz™Íz≠Íz≈Íz©ÍzÙÍ{
  10. Í{/Í{2Í{3Í{4Í{5Ñ{FÑ{GÍ{XÍ{jÍ{zÍ{—Í{ˇÍ{ÅÍ{›Í|Í|Í|OÍ|•Í|“Í|ÏÍ|ëÍ}Í}Í}-Í}cÍ}ΩÍ}ºÍ}çÍ~Í~GÍ~xÍ~œÍ~äÍÍ?ÍlÍ≥Ñ∑Í∫Í¢ÍÖÍúÍ•)Í•^Í•—Í•µÍ•éÍ™љљ    Ñ™5Ñ™6Í™HÍ™sÍ™˝Í™¡Í™ÃÍ™âÍ™éÍ™êÍ™ëÍ™òÍ≠Í≠JÍ≠wÍ≠œÍ≠ËÍ≠ûÍ∞Í∞OÍ∞sÍ∞ˇÍ∞∏Í∞¿Í∞êÍ≥Í≥CÍ≥mÍ≥‘Í≥∂Í≥ΔÍ≥ŒÍ≥£Í≥ÌÍ∑
  11. Í∑1Í∑VÍ∑\Í∑∑Í∑§Í∑®Í∑¯Í∑°Í∑ÂÍ∑îÍ∫2Í∫[Í∫≠Í∫√Í∫≈Í∫µÍ∫ÚÍ∫áÑ∫âÑ∫ãÑ∫äÍ∫åÑΩûÍΩüÑ√ Ñ√ Í√Í√AÍ√lÍ√«Í√èÍ≈Í≈RÍ≈UÍ≈VÍ≈WÍ≈XÍ≈YÑ≈iÑ≈jÍ≈®Í≈¯Í≈ÄÍ≈ÚÍ≈ïÍ…
  12. Í…,Í…KÍ…fÍ…gÍ…hÍ…ÈÍ—Í—9Í—]Í—™Í—≤Í—óÍ‘#Í‘_Í‘˛Í‘ÏÍ‘flÍŸ$ÍŸ<ÍŸ=ÍŸ>ÍŸ?ÍŸ@ÍŸAÍŸBÍŸ^ÍŸzÍŸŸÍŸÎÍ⁄Í⁄<Í⁄nÍ⁄‘Ñ⁄ŸÍ⁄⁄Í⁄∂é⁄˜Ñ⁄˘ÑΔhÑΔiÑŒ#ÑŒ$2Œ%2ŒiÑ‚¥Ñ‚œÑ„Gß„Hß    l
  13. 
  14. ˙
  15. ˙¬_π`
  16. ¶q
  17. ·∑
  18. ¶ˆ
  19. ¶˜
  20. º˘
  21. ¶z
  22. »„
  23. ¶
  24. =
  25. ¶e∏ΔÂŒ
  26. æ
  27. ç∏ Å 
  28. Z
  29. b
  30. c
  31. ¶o≤Ω Ç≈
  32. ¶å
  33. ù
  34. ¶J
  35. ·X
  36. ¶·
  37. ʥ
  38. ¶°
  39. ·À
  40. ¶ç
  41. »
  42. ¶$≤@ ÇA
  43. ¶ 
  44. ¶* À> Ç?
  45. ¶œq    Ïr
  46. Ó!ô!ö
  47. Ó?    ÏA ±! ”"?
  48. Ó#/)¨
  49. Ó)© Ã)Õ Ú)Ö
  50. Û,d
  51. ó,e
  52. D,p
  53. l,¢
  54. Û,€ H,¬
  55. ,µ
  56. Û.nÌ.⁄ Ú.∂
  57. Û/F02    Ï03
  58. Ó0›!0fl
  59. Û1ÓÌ1ò Ú1ó
  60. Û3‹5Ÿ    Ï5⁄
  61. Ó5ΔÌ5® Ú5¯
  62. Û6V
  63. à6\
  64. Û8R:)    Ï:+
  65. Ó?Ã
  66. Û?Ä
  67. ÓAG
  68. àAL
  69. ÛCÒ
  70. ÓCÓÌC› ÚCñ
  71. ÛGQ
  72. àGW
  73. ÛH~
  74. àH√
  75. ÛI’ÌIÌ ÚIÍ
  76. ÛQR
  77. àQX
  78. ÛRªÌRÈ ÚRÉ
  79. ÛSìTÿ    ÏU
  80. ÓUhVP    ÏVQ
  81. ÓV„V¡V£
  82. Û[ÚÌ[÷ Ú[ø
  83. Û`§
  84. à`¬
  85. Ûa∫
  86. àaΔ
  87. Ûa’Ìa◊
  88. Ûd
  89. åd
  90. ÛdÜÌe Úe
  91. Ûe
  92. æe.
  93. Ûií
  94. óiî
  95. Diù
  96. lj-
  97. Ûj.
  98. 
  99. j/
  100. Aj0
  101. äj1
  102. Ûq˘Ìq£ Úq€
  103. Ûuí ÚuïÌv Úv
  104. ÛxmëxnÎx⁄
  105. Ix∂
  106. àx‰
  107. Ûy^Ìym Úyn
  108. Ûyo{2    Ï{5Ì{E ›{F
  109. Û{G≥!∑™
  110. Ó™    Ì™4 Ú™5
  111. Û™6∫á!∫â
  112. Ó∫ä    Ï∫å
  113. ó∫ê
  114. ÛΩû    ÏΩüÌ√
  115.  ›√ 
  116. Û√ ≈U    Ï≈YÌ≈h ›≈i
  117. Û≈j⁄—    Ï⁄‘
  118. Ó⁄Ÿ    Ï⁄∂Î⁄ˆë⁄˜
  119. ӌ$
  120. EŒ% ‹Œh
  121. LŒi
  122. Û„F
  123. Á„G
  124.  j. %ì√8√8€.·u$.”·u,àß·u 
  125. ¿˘·uWû·u(Rã·tx5·t•6·tp=·t˘>™·tt"¿‰·yÈ&SÚ·y°*-3·u√,`À·y¬/ Æ·u≥1æï·w5Õı·u•9sú·w=mõ·utAbó·uxEUü·u|IQ÷upMñ·u Qfl·ulUì·yØXï≤·u‘\–Ú·w`Ω÷w dJç·wh1æ·t√l÷·t|pô·tΔt‡·t´wÿƒ·t€{ıç·t‘∑õ·tÜ∞zñ·vtΩkÒ·t°—=Y·t˛⁄ˆ    ·t¨Δƒ§·t „F·tø.
  126.  
  127. T E C H N O T E :
  128. Cross-Platform Communication Using the PC Compatibility Messaging System 
  129.  
  130. By Ben Manuto  
  131. <manuto@apple.com> 
  132. Apple Engineering
  133.  
  134. This Technote describes the Messaging System Architecture used in Apple's PC Compatibility and DOS Compatibility products. Specifically, the messaging system allows communication of data between the PC-based machine running on a NuBus or PCI  card and the Macintosh OS. This inter-machine communication is facilitated through a driver on the Macintosh which controls the PC card and allows it to run within the Macintosh hardware and software space.
  135.  
  136. This Technote is directed toward third-party developers who are interested in developing software for the Mac and the PC , which needs to communicate instructions or data between platforms. The applications deve”loped to use the messaging system would be intended to run specifically with AppleÕs PC Compatibility products.
  137.  
  138. This document assumes the developer is familiar with application and driver-level software development on the Macintosh platform as well as the PC. For the Mac, an understanding of the Device Manager and implementing 68K and PPC native code is essential. For the PC, an understanding of 16-bit DOS Real mode execution and x86 assembly language is useful. For development in conjunction with Window's based applications, a knowledge of 32-bit Windows programming and virtual device drivers (VxD's) is necessary. 
  139.  
  140. This document also assumes the reader is familiar with Apple's PC Compatibility products and how they function within the Macintosh OS.
  141.  
  142. Further information on Macintosh programming at the device level can be found in Inside Macintosh: Devices. For more information on Windows VxD programming (only necessary for using tßhe message system with Windows 3.x or Windows 95), see Writing Windows Virtual Device Drivers by David Thielen and Bryan Woodruff.
  143.  
  144.  
  145. About the PC Compatibility Messaging System
  146.  
  147. The PC Compatibility (or DOS Compatibility) systems currently supported by this messaging architecture are the Centris 610 DOS Compatible, PowerMac 6100/66 DOS Compatible, the Quadra 630 DOS Compatible, and any PCI-based Macintosh which includes the most recent PCI-based 100Mhz Pentium and Cyrix 5x86 PC Compatibility Cards. Currently, the only system bundled with the PCI- based cards is the PowerMac 7200/120. All of these systems must be running version 1.5 of the PC Compatibility Software or later, which includes the driver that allows the messaging system to function.
  148.  
  149. The messaging system is implemented as a 16-bit DOS real-mode driver and is used extensively in these current products to allow the PC to have access to the shared devices on the Mac (HD, CD, floppy, etc.), networking communications, f˘older sharing, and clipboard support.
  150.  
  151.  
  152. Using the Messaging System
  153.  
  154. Software programs on the Mac and the PC are capable of exchanging messages containing up to 64K of data by using the Messaging System API. Applications that plan on sharing  messages must define and understand the types of messages to be sent and received. More importantly, verification and acknowledgment of sent and received messages must be maintained by the sending and receiving applications.
  155.  
  156. The driver installed at the Mac OS startup time is called ".Symbiosis" and needs to be opened by your Macintosh application before driver calls can be made. Your program will then use device manager _Control calls to register, send, and receive messages. The PC accesses the messaging system through a software interrupt interface. The application will load x86 registers with appropriate values, a function selector, and then call the messaging systemû via an INT 5Fh call.
  157.  
  158.  
  159. Basic Messaging Concepts
  160.  
  161. Both the Mac and the PC applications accessing the messaging systems must define a 32-bit selector for their messages and a count value that denotes the number of different types of messages available for this selector. Typically, applications that are to pass messages define one selector type. Selector types can be any unique 32-bit value, so 4-character values work well (32-bit OSType). Both the Mac and the PC applications must know the message selector and they must know the number of message types associated with that selector in order to register themselves with the messaging system (See the Registering Messages section for more details on Message Selectors and Types).
  162.  
  163. The basic process of single message communication between an application on the Mac and an application on the PC is as follows:
  164.     
  165. 1) Open the messaging system and verify it is available.
  166. 2) Accurately register message selector and number of message types.
  167. 3) Install message handlers aãnd completion routines.
  168. 4) Begin transceiving messages.
  169. 5) Once the message handler is called, the application can provide space to receive the data or ignore the message.
  170. 6) After the data has been received, the receiving application should send a response to the sending application, acknowledging the data was properly received.
  171. 7) Once the acknowledge has been received, the calling application can then send another message (goto step 4) or both apps can stop sending messages.
  172. 8) After all messages have been sent, both applications must remove and deallocate all their message handlers.
  173.  
  174. Performing multiple message communication is also possible (i.e., the ability to send more than one message before receiving an acknowledge), but requires more maintenance. The intent here is to describe the basic communication between applications. Therefore, multiple message communication concepts are discussed in the Advanced Messaging Techniques section of this Technote.
  175.  
  176.  
  177.  
  178.  
  179.  
  180. Opening the Messaging System
  181.  
  182. On the Mac, the application must open the .Symbiosis driver and retrieve the refNum for the driver in order to make other message system control calls. Your application can do this using the OpenDriver function. If this returns an error, the .Symbiosis driver is not available and the messaging system cannot be used.
  183.  
  184. On the PC, the application must load the AH register with 0 and call the software interrupt INT 5Fh. If the messaging system is installed, AH = $A5 and AL  will equal the highest implemented function code, which is currently 5, when the interrupt returns. The highest implemented function code means there are a total of 5 functions supported for registering and receiving messages. This will be discussed in detail later.
  185.  
  186.  
  187. Essential Data Types
  188.  
  189. The basic data structures for accessing the messaging system on the Mac side are defined as follows:
  190.  
  191. typedef struct {
  192.     QElemPtr     qLink;
  193.     SInt16        qType;
  194.     SInt16        ioTrap;
  195.     Ptr         ioCmdAddr;
  196.     ProcPtr     ioCompletion;        // always NULL
  197.     OSErr         ioResult;            // error result info.
  198.     StringPtr    ioNamePtr;
  199.     SInt16        ioVRefNum;
  200.     SInt16        ioCRefNum;            // refNum of Symbiosis driver.
  201.     SInt16        csCode;                // messaging system function
  202.     void *        csPtr;                // pointer to procedure or data
  203.     SInt32        csData;                // data
  204.     SInt32        csData2;            // data
  205. } SBParamBlockRec, *SBParamBlockRecPtr;
  206.  
  207. The SBParamBlockRec is virtually the same as a standard paramBlockRec except only the fields used by the messaging system are included for the data area. The only fields needed for messaging are the ioCRefNum and csCode for calling the driver, and then the csPtr and csData fields which are used to point to other structures that are defined below. The different csCode's used for calling the messaging system are defined below:
  208.  
  209. enum {
  210.     eSendMessage             = 800,    // Send a message
  211.     eInstallMsgHandler     = 801,    // Install a message handler
  212.     eRemoveMsgHandler         = 802,    // Remove message handler
  213.     eRegisterMessage         = 803    // Register message type
  214. };
  215.  
  216. The data structures used for sending and receiving messages are below:
  217.  
  218.  
  219. typedef struct MsgPBlk {
  220.     struct MsgPBlk*    msgQLink;    // Pointer to next MsgPBlk
  221.     SInt16                msgQType;    // Queue Flags
  222.     SInt16                msgCmd;        // The message type or command
  223.     SInt32                msgParam1;    // Message parameter 1
  224.     SInt32                msgParam2;    // Message parameter™ 2
  225.     void*                msgBuffer;    // Ptr to the msg data buffer
  226.     SInt32                msgReqCount;    // Requested data length
  227.     SInt32                msgActCount;    // Actual data length
  228.     MsgCompletionUPP    msgCompletion;    // Ptr to comp. rtn. or NULL
  229.     SInt16                msgResult;    // The result of msg operation
  230.     UInt16                msgFlags;    // Message flags
  231.     UInt32                msgUserData;    // refCon (a5, etcÉ)
  232. } MsgPBlk, *MsgPBlkPtr;
  233.  
  234.  
  235. typedef struct MsgRecElem {
  236.     struct MsgRecElem*        recQLink;        // Next queue element
  237.     SInt16                    recQType;        // queue flags
  238.     SInt16                    recFlags;        // Not used...Set to zero
  239.     MsgReceiveUPP            recProc;        // Ptr to the receive proc.
  240.     SInt16                    recCmdBase;    // Msg Selector base.
  241.     SInt16                    recCmdCount;     // # of msgTypes
  242.     UInt32                    recUserData;     // refCon (could be A5...)
  243. } MsgRecElem, *MsgRecElemPtr;
  244.  
  245.  
  246. The MsgPBlk is used for sending and receiving data and the MsgRecElem is used for notification of incoming messages.
  247.  
  248. For the ‰PC application using the messaging system, the PC Data structures and function ID constants are defined below:
  249.  
  250. enum {
  251.     eIsAvailable             = 0        // Index for is available
  252.     eSendMessage             = 1        // Index for Send func
  253.     eInstallMsgHandler     = 2        // Index for Install Msg Handler func
  254.     eRemoveMsgHandler         = 3        // Index for Remove Msg Handler func
  255.     eRegisterMessage         = 4        // Index for Register Msg
  256.     eVersionCheck             = 5        // Index to get the version numbers
  257. };
  258.  
  259. // some basic types used for the MsgPBlk and MsgRecElem structures.
  260.  
  261. typedef char     SInt8;
  262. typedef short    SInt16;
  263. typedef long    SInt32;
  264. typedef unsigned char  UInt8;
  265. typedef unsigned short UInt16;
  266. typedef unsigned long  UInt32;
  267. typedef char __far* Ptr32;
  268.  
  269.  
  270.  
  271.  
  272.  
  273.  
  274.  
  275.  
  276.  
  277.  
  278.  
  279. typedef struct MsgPBlk {                                                                       
  280.    struct MsgPBlk*      link;        // Pointer to the next MsgPBlk.
  281.    SInt16                 msgCmd;     // The message commanÚd or type
  282.    SInt32                 msgParam1;    // Param 1
  283.    SInt32                 msgParam2;    // Param 2
  284.    UInt32                 msgCompletion;    // Ptr to the completion routine
  285.    Ptr32                msgBuffer;     // Ptr to the data buffer
  286.    SInt32                 msgReqCount;    // Length of the data
  287.    SInt32                 msgActCount;    // # of bytes actually transfered
  288.    SInt8                  msgResult;    // The err code after complete or 1
  289.    UInt8                  msgFlags;    // Not used, init to zero.
  290.    UInt32                 msgUserData;     // for caller's use
  291.    UInt32                 msgVXD;        // Used by VxD
  292. } MsgPBlk, *MsgPBlkPtr;
  293.  
  294. typedef struct MsgRecElem {
  295.    struct MsgRecElem*    Link;
  296.    SInt32                Code;
  297.    SInt16                cmdBase; // the base message number for this proc
  298.    SInt16                cmdCount;// the # of message numbers for this proc
  299.    UInt32                userData;    // for caller's use
  300.    UInt32                recVXD;     // reserved - Used by VxD
  301. } MsgRecElem, *MsgRecElemPtr;
  302.  
  303. Registering Messages with the Message System
  304.  
  305. The process of message registration requires both the Mac application and the PC appli3cation to be aware of a predefined set of message types that are defined by the application developer. Both applications are aware of the data formats of these messages and know how to decode and use certain parts of the messages based on their distinct message type ID. These message types are grouped together by a message selector (4-byte value of type OSType) known to both the Mac and the PC application.
  306.  
  307. Both applications send the message selector and the number of message types to the message system and the message system returns a cmdBaseID (See FigureÀ 1).
  308.  
  309. Figure 1. Registering a message selector and message types.
  310.  
  311.  
  312.  
  313.  
  314.  
  315.  
  316.  
  317.  
  318.  
  319.  
  320.  
  321.  
  322.  
  323.  
  324.  
  325. Once the set of messages for the Mac and PC applications has been registered with the message system, each individual message has a unique value (called a msgCmd) which ranges from the msgCmdBaseID to the total number of messages - 1. When the applications send and receive messages, they will reference particular message types through the msgCmdBaseID plus some value which specifies the message type. The resulting value is the msgCmd.
  326.  
  327.  
  328. Registering a Message on the Mac
  329.  
  330. To register messages on the Mac, your application must fill out a SBParamBlockRec  make the appropriate driver call. To do this, fill out the foÆllowing fields of a SBParamBlockRec:
  331.  
  332. -->    ioCRefNum =             <refNum of the .Symbiosis driver>;
  333. -->    ioVRefNum =             0;
  334. -->    ioCompletion =         0;
  335. <--    ioResult     =             0;
  336. -->    csCode =                 eRegisterMessage;
  337. <->    csPtr =                 <message selector>;
  338. -->    csData =                 <number of message types>;
  339.  
  340. The message selector entered in the csPtr field should by a 4-byte value of type OSType. The csData field should be the number of message types registered.
  341.  
  342. Make the driver call using the PBControlImmed function. If the registration is successful,  the ioResult will equal noErr and the csPtr will contain a message base command (msgCmdBaseID) value which is used in the message send and receive parameter blocks.
  343.  
  344. Registering a Messaïge on the PC
  345.  
  346. To register a message on the PC, load the 32-bit message selector into the EBX register and put the number of message types in CX. Then call INT 5Fh with AH equal to the registerMessage function ID (4). On return from the interrupt, BX will contain a message command base ID which must be used in the MsgPBlk's and MsgRecElem's. A sample function called MsgRegister, which passes in a selector and count (number of msg types) and returns the command base ID, is shown below:
  347.  
  348. MsgRegister PROC FAR C  msgSel:DWORD, msgCount:WORD, msgCmmd:WORD
  349.  
  350.    mov   ebx,msgSel            ; load EBX with the msgSelector.
  351.    mov   cx,msgCount            ; load CX with the msgCount
  352.    mov   ah,registerMessage    ; load AH with the function ID.
  353.    int   05Fh                    ; make the interrupt call.
  354.    
  355.    mov   dx,bx                    ; move BX to DX.
  356.    mov   bx,msgCmmd            ; Put the address of msgCmd in BX.
  357.    mov   [bx],dx                ; Return the msgCmd value.
  358.    ret
  359. MsgRegister ENDP
  360.  
  361.  
  362. Sending a Message from the Mac
  363.  
  364. For either machine to send a message ıto the other, a MsgPBlk must be filled out and passed to the message system. The message system function for sending messages is always executed asynchronously, but the actual driver call is still made with PBControlImmed function and the ioCompletion field of the SBParamBlockRec should be set to  NULL. The SBParamBlockRec is only used to send the MsgPBlk to the messaging system, so the completion routine function pointer is filled in the ioCompletion field of the MsgPBlk. The csPtr field on the SBParamBlockRec should be a ptr to the completed MsgPBlk.
  365.  
  366. To send a message, your application should fill out the MsgPBlk as follows:
  367.  
  368. -->    msgCmd =             <message cmdBase ID + type ID>;
  369. -->    msgParam1 =         <any 32-bit value>;
  370. -->    msgParam2 =         <any 32-bit value>;
  371. -->    msgBuffer =         <pointer to a data buffer (64K max)>;
  372. -->    msgReqCount =        <size (in bytes) of the data buffer)>;
  373. <--    msgActCount =        0;         // init to zero!
  374. -->    msgComúpletion =     <pointer to completion rtn. or NULL>;
  375. <--    msgResult =         0;        // init to zero.
  376. -->    msgFlags =             0;        // always set to zero!
  377. -->    msgUserData =        <any 32-bit pointer of value>;
  378.  
  379.  
  380. The msgCmd field should contain a value equal to the message cmdBase ID returned from the message registration function plus the message type value for this message. If your application registered 15 message types for a particular selector (for which a cmdBase ID was returned), cmdBaseID <= msgCmd < (cmdBaseID + number of message types). The message handler on the PC will receive the msgCmd and can determine the message type ID by subtracting the cmdBaseID from the msgCmd. The format and/or types of these messages are predefined and recognizable by the applications which defined them.
  381.  
  382. The msgParam1 and msgParam2 fields can contain any 32-bit values the sending application wishes to place in them. The receiving function on the PC will have access to these paramters before the msgBuffer is actually transferred to the PC. Sõo these fields can be used for messages without a data block or they can be used to determine if the receiving application wants to receive the data buffer.
  383.  
  384. The MsgReqCount field should contain the length (in bytes) of the data that is contained within the msgBuffer block. This does not mean it should be the length of the msgBuffer block, only the length of the data you wish to send that is contained from the start of the msgBuffer (e.g.,  msgReqCount <= size of buffer). The msgActCount field is filled in by the message system contains the number of bytes that were actually sent to the PC.
  385.  
  386.  
  387. The msgUserData is a refCon that can be a 32-bit value or a pointer to data. This field does not get transferred to the PC, but it available for use when the completion routine gets called.
  388.  
  389. Once the message is sent, the msgResult field will be set to 1 to mark that the message is currently busy. Once the completion routine is called, msgResult will be 0 (noErr) or -3 (msgTimeout).
  390.  
  391. Note: The completion routinóe gets called at Deferred Task time and can use registers D0-D2, A0, and A1. All other registers must be saved and restored. A0 will contain a pointer to the MsgPBlk. A5 must be restored and saved if access to globals are necessary and you are coding under 68K. Use the msgUserData field hold onto your A5 world.
  392.  
  393. If your application is PPC Native, universal proc pointers and mixed-mode function definitions have been provided in the Messaging.h file included in the MessageTest tool source code that accompanies this Technote. Obviously, no save and restore of global space is necessary when running from PPC Native code.
  394.  
  395. Sending a Message from the PC
  396.  
  397. The MsgPBlk on the Mac and the MsgPBlk on the PC are virtually identical as far as the fields of the data structure the messaging application must use. The PC application should build the MsgPBlk in the same manner as described in the previous section and then send it through the message system interface on the PC.
  398.  
  399. To send a message from the PC, ES:BX üshould contain a far pointer to the MsgPBlk. AH should contain the function ID for sendMessage (1). Then the application should make the INT 5Fh call. The message will be queued and the msgResult field will be set to 1. Once the message has been sent, the completion routine will be called.
  400.  
  401. Your completion routine can be done in C code as well as assembly, but you must remember to use the __loadds keyword in your function prototype in order to have access to globals within your functions data segment.
  402.  
  403. Note: The completion routine specified will be called with a far call, so your completion routine must return with a RETF instruction (if you are writing your completion routine in C, this is usually not an issue). Interrupts are also turned off when the completion routine is called and the function should not turn interrupts on for any reason. The completion routine can use the AX, BX, CX, DX, DI, SI, ES, and DS registers. When the completion routine is called ES:BX contains a pointer to the MsgPBlk.
  404.  
  405. See Ãthe Test.c and Mesg.asm files for the PC MsgTest tool that accompanies this Technote for sample code.
  406.  
  407.  
  408. Receiving a Message
  409.  
  410. To receive a message, your application must install a message handler function. A message handler function must be unique to every message selector that has been registered with the messaging system, but is the same function for every message type that belongs to a particular selector. In other words, if your application registers a message selector 'abcd' which has 15 message types associated with it, your application only has to install one message handler that will know how to process all 15 types of messages. The receive function can determine the message type by subtracting the cmdBaseID from the msgCmd value in the MsgRecElem.
  411.  
  412. The purpose of a message handler is to examine the msgCmd, msgParam1 and msgParam2 fields of the message that has been sent to determine if there is any data to be retrieved from the message. If tñhere is data the receiving application wants to get, it must provide a pointer to a MsgPBlk with space allocated for the msgBuffer field for receiving the data. The msgReqCount field of the MsgPBlk should also contain the number of bytes the application expects to receive or the absolute size in bytes of the msgBuffer (i.e., 0 < msgReqCount <= size of msgBuffer). The messaging  system will only write a maximum of msgReqCount bytes or less of data to the msgBuffer block. 
  413.  
  414.  
  415. Once a MsgPBlk has been provided, the messaging system will then retrieve the data into the msgBuffer field and update the msgActCount field of the MsgPBlk with the actual number of bytes transferred. If msgReqCount == msgActCount, msg Result equals noErr (0). If msgReqCount < msgActCount, msgResult will equal -1 (msgOverrun). If msgReqCount > msgActCount, msgResult will equal -2 (msgUnderrun). If msgResult equals -3 (msgTimeout), a time out error occurred and the transferal of data may not be complete. After the data has beefln received, the completion routine specified in the MsgPBlk will be called.
  416.  
  417. Note: The msgBuffer pointer will be advanced msgActCount bytes after the data transfer has been made (i.e., the pointer will point the end of the msgBuffer) and needs to be reset back to the start of the buffer after the completion routine is called in order to access the transfered data. This behavior is consistent for the Mac and the PC.
  418.  
  419.  
  420. Receiving a Message on the Mac
  421.  
  422. To establish the ability for the Mac application to receive messages, the MsgRecElem should be built and installed. Typically, this should be done before the application sends a message so it is able to receive an acknowledge from the receiving application. Build a MsgRecElem as follows:
  423.  
  424. -->    recFlags =         0;     // not used, init to zero.
  425. -->    recProc =        <pointer to msg receive handler function>;
  426. -->    recCmdBase =    <cmdBaseID for this app's msg Selector>;
  427. -->    recCmdCount =    <Number of msgTypes for this msg selector>;
  428. -->    recUserData =    <any 32-bit value or pointer>;
  429.  
  430. To ìinstall the msg receive handler, build the MsgRecElem and then build an SBParamBlcokRec as follows:
  431.  
  432. -->    ioCRefNum =         <refNum of the .Symbiosis driver>;
  433. -->    ioVRefNum =         0;
  434. -->    ioCompletion =     0;
  435. <--    ioResult =             0;
  436. -->    csCode =             eInstallMsgHandler ;
  437. -->    csPtr =             <pointer to MsgRecElem>;
  438. -->    csData =            0;
  439. -->    csData2 =            0;
  440.  
  441. Then install the msg handler by passing the built SBParamBlock to PBControlImmed.
  442.  
  443. When the Mac receives a message from the PC, the message handler function pointed to by recProc in the MsgRecElem will be called. Your handler is called at interrupt time with interrupts masked at the slot interrupt level. When the handler is called, D0.w contains the msgCmd, D1 contains msgParam1, and D2 contains msgParam2 from the sending applications MsgPBlk. 
  444.  
  445. Based on these three values passed to the message handler, it must determine whether there is data to be received or whether it wants to receive the data. If the handler decides to receive the message data, it must retur≤n a pointer to a MsgPBlk that has an allocated msgBuffer and where the msgReqCount field is set to the number of bytes it expects to or is able to receive (see the previous section). The MsgPBlk should be returned in A0. If the MsgHandler decides not to receive the data, it should return 0 in A0.
  446.  
  447. The completion routine specified in the MsgPBlk will be called after the data has finished transmitting through the message system. The completion routine is called at deferred task time and can use registers A0, A1, D0, D1, and D2. All other registers must be saved and restored. A0 will contain a pointer to the MsgPBlk. (The universal procedure prototypes automatically handle moving the MsgPBlk into the function for PPC Native C functions.)
  448.  
  449.  
  450. Receiving a Message on the PC
  451.  
  452. The process for receiving a message on the PC is much the same as on the Mac. Build a MsgRecElem just as was shown in the previous section. To install the message handler, place a Úpointer to MsgRecElem in ES:BX, set AH to installMsgHandler (2) and call INT 5Fh.
  453.  
  454.  
  455. The installed message handler routine is called at interrupt time with interrupts turned off. The AX, BX, CX, DX, SI, DI, ES, and DS registers are available for use. When it is called, AX contains the msgCmd from the sending application's MsgPBlk. ECX contains msgParam1 and EDX contains msgParam2 from the sending application's MsgPBlk. DS:DI contains a pointer to the MsgRecElem.
  456.  
  457. Just the same as in the Mac message handler, the PC message handler must determine whether there is data to be received or whether it wants to receive the data in the message. If it does, it must return a pointer to a MsgPBlk in ES:BX, otherwise it should set ES:BX to NULL.
  458.  
  459. After the data has been received by the PC, the completion routine specified in the MsgPBlk will be called. ES:BX will contain the pointer the MsgPBlk and the function can use the AX, BX, CX, DX, DI, SI, ES, and DS registers. All other registeÃrs must be saved and restored.
  460.  
  461. Note:  Both the  message handling routine and the completion routine are called at interrupt time with interrupts turned off. Both functions should adhere to any rules of execution during interrupt time for a PC system and should not at any time turn interrupts back on. 
  462.  
  463.  
  464. Removing the Message Handlers
  465.  
  466. Message handlers must be removed when applications that installed them are no longer active. If the message handler is not removed, the messaging system could attempt to call the handler again. If the application has been terminated, it's a good bet that both the PC and Mac will crash.
  467.  
  468. To remove a message handler on the Mac, create a SBParamBlockRec and specify the eRemoveMsgHandler function code for the csCode. The csPtr field would be a pointer to the MsgRecElem that was used to install the message handler. Pass the SBParamBlockRec to the messaging system using a PBControl call.
  469.  
  470. To remove a message handler on the PçC, set the AH register to removeMsgHandler (3), set ES:BX to a pointer to the MsgRecElem used to install the handler, and make an INT 5Fh call.
  471.  
  472.  
  473. Advanced Messaging System Techniques
  474.  
  475. As described in the Basic Messaging Concepts  section of this Technote, the goal here is introduce developers to simple methods of performing Mac <--> PC communication using the PC Compatibility Card's messaging system interface. That basic level of communications means two applications send information to each one message at a time (i.e., the sending application does not send a second message to a receiving application until the receiving application has acknowledged it actually received the data of the sent message). Some applications may have a need to send multiple threads of messages back and forth before awaiting a reply, however. The good news is that this can be done. The bad news is that the developer is responsible for managing all of the message types and basic send/acknowledge protocols the aæpplications should adhere to.
  476.  
  477. This management of messages is primarily performed in the message handler function which would be required to maintain a list of MsgPBlk's to grab all of the data being sent in. The only limit being how much memory the application can allocate to hold on to this incoming data and how well the message parameters and data are defined so acknowledging messages can be adequately returned to the sending application
  478.  
  479. Figure 2. Basic data flow for multiple message communication.
  480.  
  481. 
  482.  
  483. As shown in Figure 2, a message installer can install a MsgRecElem and some number of n MsgPBlk's with msgBuffer's allocated. When the MsgHandler is called, it searches the list for an available MsgPBlk (one in which the msgResult field <= 0, and the msgActCount = 0, so it knows the msgBuffer is empty) and returns it to the messaging system. Each MsgPBlk may have its own completion routine (if, for instance, one type of MsgPBlk was to be used for a specific message type) or can use÷ one particular completion routine. So the number of completion routines <= the number of MsgPBlk's in the list.
  484.  
  485. After a MsgPBlk's completion routine is called, it can handle the data in any method needed, but then needs to notify the application that the data is ready. Either the msgBuffer needs to be detatched from the MsgPBlk (and a new buffer attached) or the application must have some way of marking the MsgPBlk as busy until the application can retrieve and process the data. The MsgPBlk can then be reset and the MsgHandler can use it again for other incoming messages.
  486.  
  487. The application message handler is then responsible for sending the acknowledge message back to the sending application after it has verified the length and/or quality of the data. 
  488.  
  489. What is described here is one possible methodology for handling multiple message communication. Simpler methods or more complex methods may be needed based on the complexity of data to be exchanged. The level of this complexity is left to the developôer, however. As long as the basic criteria are met as to when the messaging system has access to the paramBlock's and when the application has access to them, any system should work.
  490.  
  491. Similar messaging algorithms should be maintained for both the Mac and the PC applications that communicate information. All transactions between the Mac and the PC are made asynchronously at interrupt time.
  492.  
  493.  
  494. Limitations
  495.  
  496. As stated earlier, the messaging system is capable of sending individual data packets of up to 64K. All data transfers between the Mac and the PC occur at interrupt time. This can sometimes have an effect on other software that may rely on processing data during interrupt time. Therefore, it is highly reccommended that if software designed to use this messaging system requires transmission of large blocks of data, the packet size used for each message sent should be reduced.
  497.  
  498. There is no absolute rule to follow here and the effect on other interrupt dependent software running at the same time as th‡e data packets being transmitted to and from the PC Compatibility Card also depends on the capability of the hardware being used. As a general rule, however, it is advised that if the software being developed needs to transmit more than 1 MB of data at any particular time, the message packet size should be reduced to 32K or 16K. This will allow interrupts to not be turned off for as long a period of time to process the data transfers and allow other interrupts to execute and catch up.
  499.  
  500.  
  501.  
  502. The MacMsgTest and PCMsgTst Tools
  503.  
  504. This Technote is accompanied by two tools, one for the Mac and one for the PC, that perform very simple messaging. MacMsgTest is written entirely in C and is designed and compiled to run PPC Native. PCMsgTst is written in C and x86 assembly. Source code, header files, and makefiles are included for each tool. The necessary build environments are not included.
  505.  
  506. The tools are available on Apple's Developer World website (http://www.developer.apple.com/) and on the Developer CD.
  507.  
  508. Please see eƒach tool's individual ReadMe files for further information on executing and building MacMsgTest and PCMsgTst.
  509. Summary of the Messaging System
  510.  
  511. Note: All of the Macintosh constants, data types, universal procedure pointers, and universal procedure definitions can be found in the "Messaging.h" file in MacMsgTest tool that accompanies this technote.
  512.  
  513. Constants (Mac)
  514.  
  515. #define kDriverName    "\p.Symbiosis"    // The name of the driver
  516.  
  517. enum {
  518.     eSendMessage            = 800,    // Send a message
  519.     eInstallMsgHandler        = 801,    // Install a message handler
  520.     eRemoveMsgHandler        = 802,    // Remove message handler
  521.     eRegisterMessage        = 803    // Register message type
  522. };
  523.  
  524.  
  525. enum {
  526.     msgNoError        = 0,            // No error
  527.     msgOverrun        = -1,            // More data was available
  528.     msgUnderrun        = -2,            // Less data was available
  529.     msgTimeout        = -3            // Timeout error
  530. };
  531.  
  532.  
  533.  
  534. Data Types (Mac)
  535.  
  536. typedef struct {
  537.     QElemPtr     qLink;
  538.     SInt16        qType;
  539.     SInt16        ioTrap;
  540.     Ptr         ioCmdAddr;
  541.     çProcPtr     ioCompletion;        // always NULL
  542.     OSErr         ioResult;            // error result info.
  543.     StringPtr    ioNamePtr;
  544.     SInt16        ioVRefNum;
  545.     SInt16        ioCRefNum;            // refNum of Symbiosis driver.
  546.     SInt16        csCode;                // messaging system function
  547.     void *        csPtr;                // pointer to procedure or data
  548.     SInt32        csData;                // data
  549.     SInt32        csData2;            // data
  550. } SBParamBlockRec, *SBParamBlockRecPtr;
  551.  
  552. typedef struct MsgPBlk {
  553.     struct MsgPBlk*    msgQLink;    // Pointer to next MsgPBlk
  554.     SInt16                msgQType;    // Queue Flags
  555.     SInt16                msgCmd;        // The message type or command
  556.     SInt32                msgParam1;    // Message parameter 1
  557.     SInt32                msgParam2;    // Message parameter 2
  558.     void*                msgBuffer;    // Ptr to the msg data buffer
  559.     SInt32                msgReqCount;    // Requested data length
  560.     SInt32                msgActCount;    // Actual data length
  561.     MsgCompletionUPP    msgCompletion;    // Ptr to comp. rtn. or NULL
  562.     SInt16                msgResult;    // The result of msg operation
  563.     UInt16                msgFlags;    // Message flags
  564.     UInt32                msgUserData;    // refCon (a5, etcÉ)
  565. } MsgPBlk, *MsgPBlkPtr;
  566.  
  567. typedef struct MsgRecElem {
  568.     struct MsgRecElem*    recQLink;    // Next queue element
  569.     SInt16                recQType;    // queue flags
  570.     SInt16                recFlags;    // Not used...Set to zero
  571.     MsgReceiveUPP        recProc;    // Ptr to the receive proc.
  572.     SInt16                recCmdBase;    // Msg Selector base.
  573.     SInt16                recCmdCount;     // # of msgTypes
  574.     UInt32                recUserData;     // refCon (could be A5...)
  575. } MsgRecElem, *MsgRecElemPtr;
  576.  
  577.  
  578. Universal ProcPtr and Procedure Definitions
  579.  
  580. #if GENERATINGCFM
  581. typedef UniversalProcPtr MsgCompletionUPP;
  582. typedef UniversalProcPtr MsgReceiveUPP;
  583. #else
  584. typedef ProcPtr MsgCompletionUPP;
  585. typedef ProcPtr MsgReceiveUPP;
  586. #endif
  587.  
  588.  
  589. enum {
  590.     uppMsgReceiveProcInfo = kRegisterBased
  591.         | REGISTER_ROUTINE_PARAMETER(1, kRegisterA1, 
  592.                                       SIZE_CODE(sizeof(MsgRecElemPtr)))
  593.         | REGISTER_ROUTINE_PARAMETER(2, kRegisterD0,
  594.                                       SIZE_CODE(sizeof(short)))
  595.         | REGISTER_ROUTINE_PARAMETER(3, kRegisterD1, 
  596.                                       SIZE_CODE(sizeof(long)))
  597.         | REGISTER_ROUTINE_PARAMETER(4, kRegisterD2, 
  598.                                       SIZE_CODE(sizeof(long)))
  599.         | REGñISTER_RESULT_LOCATION(kRegisterA0)
  600.         | RESULT_SIZE(kFourByteCode),
  601.     
  602.     uppMsgCompletionProcInfo = kRegisterBased
  603.         | REGISTER_ROUTINE_PARAMETER(1, kRegisterA0, 
  604.                                      SIZE_CODE(sizeof(MsgPBlkPtr)))
  605.         | REGISTER_RESULT_LOCATION(kRegisterA0)
  606.         | RESULT_SIZE(kFourByteCode)
  607. };
  608.  
  609.  
  610. #if GENERATINGCFM
  611. #define NewMsgReceiveProc(userRoutine) \
  612.         (MsgReceiveUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), \
  613.                                          uppMsgReceiveProcInfo, \
  614.                                          GetCurrentArchitecture())
  615. #else
  616. #define NewMsgReceiveProc(userRoutine) \
  617.         ((MsgReceiveUPP) (userRoutine))
  618. #endif
  619.  
  620.  
  621. #if GENERATINGCFM
  622. #define NewMsgCompletionProc(userRoutine) \
  623.         (MsgCompletionUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), \
  624.                                            uppMsgCompletionProcInfo, \
  625.                                            GetCurrentArchitecture())
  626. #else
  627.  
  628. #define NewMsgCompletionProc(userRoutine) \
  629.         ((MsgCompletionUPP) (userRoutine))
  630. #endif
  631.  
  632.  
  633.  
  634.  
  635. Note: All of the PC constants and data types for assembly language programming can be found in the "PCMesg.inc" file that is part of tÒhe PCMsgTst tool that accompanies this Technote. Constants and data types for C programming can be found in the PCMesg.h file that is included 
  636.  
  637. Constants (PC)
  638.  
  639. enum {
  640.     eIsAvailable = 0            // Index for is available
  641.     eSendMessage = 1            // Index for Send func
  642.     eInstallMsgHandler = 2        // Index for Install Msg Handler func
  643.     eRemoveMsgHandler = 3        // Index for Remove Msg Handler func
  644.     eRegisterMessage = 4        // Index for Register Msg
  645.     eVersionCheck = 5            // Index to get the version numbers
  646. };
  647.  
  648.  
  649.  
  650.  
  651. Data Types (PC)
  652.  
  653. // some basic types used for the MsgPBlk and MsgRecElem structures.
  654.  
  655. typedef char     SInt8;
  656. typedef short    SInt16;
  657. typedef long    SInt32;
  658. typedef unsigned char  UInt8;
  659. typedef unsigned short UInt16;
  660. typedef unsigned long  UInt32;
  661. typedef char __far* Ptr32;
  662.  
  663.  
  664. typedef struct MsgPBlk {                                                                       
  665.    struct MsgPBlk*    link;            // Pointer to the next MsgPBlk.
  666.    SInt16             msgCmd;         // The message command or type
  667.    SYInt32             msgParam1;        // Param 1
  668.    SInt32             msgParam2;        // Param 2
  669.    UInt32             msgCompletion;    // Ptr to the completion routine
  670.    Ptr32            msgBuffer;         // Ptr to the data buffer
  671.    SInt32             msgReqCount;    // Length of the data
  672.    SInt32             msgActCount;    // # of bytes actually transfered
  673.    SInt8              msgResult;        // The err code after complete or 1
  674.    UInt8              msgFlags;        // Not used, init to zero.
  675.    UInt32             msgUserData;     // for caller's use
  676.    UInt32             msgVXD;            // Used by VxD
  677. } MsgPBlk, *MsgPBlkPtr;
  678.  
  679.  
  680.  
  681.  
  682.  
  683.  
  684. typedef struct MsgRecElem {
  685.    struct MsgRecElem*    Link;
  686.    SInt32                Code;
  687.    SInt16                cmdBase;   // the base message number for this proc
  688.    SInt16                cmdCount;  // the # of message numbers for this proc
  689.    UInt32                userData;  // for caller's use
  690.    UInt32                recVXD;       // reserved - Used by VxD
  691. } MsgRecElem, *MsgRecElemPtr;
  692.  
  693.  
  694.  
  695. Summary    
  696.  
  697. The Messaging System Architecture described in this Technote is compatible with the PC Compatibility Software v1.5 or later which is installable on all DOS Compatible and PC Compatible products shipped by Apple. This includes the Centris 610 DOS Compatible, the Quadra 630 DOS Compatible, the PowerMac 6100 DOS Compatible, the 7200 PC Compatible, and all PCI based Macintosh's which support the 12" 100 MHz Pentium and 7" 100MHz Cyrix 5x86 PC Compatibility Cards.
  698.  
  699. Future releases of the PC Compatibility Software may h§ave modifications to Messaging System Architectures that will require updates of the software Interface described in this Technote.
  700.  
  701.  
  702. Acknowledgments                                                    
  703. Thanks to Rand Crippen, Craig Keithley and Daev Roehr for reviewing this Technote. Special thanks to Scott Coleman for his input into this technote and his ongoing support of Cross-Platform projects. An added thanks to Daev Roehr and Scott Coleman for their help with the sample tools which accompany this Technote.
  704.  
  705. I would also like to thank Markeeta Canada whose ongoing work and support of the PC Compatible products has been above and beyond what anyone could've expected.
  706.  
  707. ZÿÿN°DSET≠ÿÿ.H@34ÿÿÿÿÿÿ·uèΔ≤:…·t¸fi6ÿÿ*èΔ≤008√ÿ ÿÿÿÿ√8¡ddPro ≠ ‘
  708. 9≈    àp8∞Á @L7Ωÿÿÿÿÿÿ    1    ÿÿÿÿÿÿÿÿ8¡ˆ ¡ddPro0¡˚ÿòÿo
  709. ⁄ö, Palatino
  710. .ÿ+ŒMessaging System ˜¡ˆ ¡ddPro0¡˚flÕÿ÷
  711. /M(+     Application ˜¡d
  712. dPro     ‘
  713. 9≈q!%"!%!"!""!"H Ÿ¡ddPro
  714. ¡ddProÿÿÿÿÿÿ    14@B¡ˆ ¡ddPro(¡˚ÿÃÿø
  715. 3AD
  716. (=
  717. MsgRecElem ˜¡ddPro ‘ÿÿÿÿÿÿ
  718. 9≈QiG¢•    ÿÿÿÿÿÿÿÿX¡ˆ ¡ddPro(¡˚ÿ}ÿœ
  719. yN‚z“ +RFMsg ¡ddPro(á(⁄QHandler ˜ Ÿ¡d
  720. dPro     ‘
  721. 9≈q[_jfjc[_[c[fjc"[c¸ Ÿ¡ddPro
  722. ¡ddProÿÿÿÿÿÿ    1#KE≠¡ˆ ¡ddPro(¡˚ÿÔÿ¯
  723. "HF≥* (,Q    Incoming ¡ddPro(£ + Msg ¡ddPro(»•(BK Notification ˜¡ddPro
  724. 9≈    ÿÿÿÿÿÿÿÿ"∑•`m≠∫˝ZZ¡d
  725. dPro     ‘qˆ!ˇ˚!ˇ!˚!ˆ˚"y˚¨ Ÿ¡ddPro
  726. ¡ddProÿÿÿÿÿÿ    1)≥@°¡ˆ ¡ddPro(ÿÿ¡˚ÿÎÿz
  727. (™A“@(2∫MsgPBlk ¡ddPro(ÿÿ0`+ or NIL ˜¡ddProÿÿÿÿÿÿ
  728. 9≈1Ï:∂    ÿÿÿÿÿÿÿÿ8¡ˆ ¡ddPro(¡˚ÿ#ÿÂ
  729. Ó:ΔÙ(†>List of MsgPBlk's ¡ddPro(≤ + with allocated ¡ddPro(˝`+
  730. msgBuffer's.
  731. ¡ddPro(˛+ (1...n) ˜¡d
  732. dPro     ‘
  733. 9≈q¢^°e¢b°e°b°^¢b"°b Ÿ¡ddPro
  734.  ‘ÿÿÿÿÿÿ    Qi¨¢á    ÿÿÿÿÿÿÿÿX¡ˆ ¡ddPro(¡˚ÿ≠ÿD
  735. t¯˘Ûñà(~πRcv ¡ddPro(b•(≈¶Comp. ¡ddPro(˚`(‰”Routine. ˜ Ÿ ‘ÿÿÿÿÿÿ
  736. 9≈    Qi¢:    ÿÿÿÿÿÿÿÿX¡ˆ ¡ddPro(¡˚ÿ≠flë
  737. t˘4ñà(~Rcv ¡ddPro(b•(≈Comp. ¡ddPro(˚`(‰ Routine. ˜ Ÿ¡Øÿÿ•¡Öÿÿ• ◊¡´
  738. 9≈"∫æ µ¡Öÿÿ• ◊ Ù¡Öÿÿ•¡Øÿÿ• ≤ Ù ‘"∑æ"∑í"∑ô"∑û Ÿ¡Øÿÿ• ¿ Ù ◊¡d
  739. dPro     ‘qZÃiÌiÃZÆ\É^ÌiÃ"›ÙI Ÿ¡ddPro
  740. ¡d
  741. dPro     ‘qZii^\Zi"›&J Ÿ¡ddPro
  742. ¡Øÿÿ•¡Öÿÿ• ◊¡´"^Ñ? µ¡Öÿÿ• ◊ Ù¡Öÿÿ•¡Øÿÿ• ≤ Ù ‘"]Ñ"]Ø"]ß"]æ"]í"]ô"]û"]"]     Ÿ¡Øÿÿ• ¿ Ù ◊ ‘ÿÿÿÿÿÿ    QËÖ    ÿÿÿÿÿÿÿÿX¡ˆ ¡ddPro(¡˚ÿ ÿ
  743. ÖØú|à(àêApp. ¡ddPro(˙•(ëâMessage ¡ddPro(∏ (ö†
  744. Handler(s) ˜ Ÿ ‘ÿÿÿÿÿÿ
  745. 9≈    Qh¡@    ÿÿÿÿÿÿÿÿX¡ˆ ¡ddPro(¡˚ÿ~ÿï
  746. xŒ:J`(≠Message ¡ddPro(4 +     Installer ˜ Ÿ¡ˆ ¡ddPro(¡˚ÿΔÿ
  747. fât(på(1...m) ˜¡d
  748. dPro     ‘
  749. 9≈q≤ßÍèÍèÁßÀâ≤åÍè"ıÓ" Ÿ¡ddPro
  750. ¡d
  751. dPro     ‘q≤ÿÍÍÿ≤ÀÁÍÿ" ›  Ÿ¡ddPro
  752. ¡ddProÿÿÿÿÿÿ    1-ÒD¡ˆ ¡ddPro(¡˚ÿÊÿ,
  753. ,ÏEU`(6Ô MsgPBlk w/ ¡ddPro(£•+     msgBuffer ˜¡ddPro¡ddProÿÿÿÿÿÿ
  754. 9≈1œÉ∏¡ˆ ¡ddPro(¡˚ÿQÿ3
  755. ¥Æ≤!Í@(¯ÍA notification for ¡ddPro(Ì + the application ˜¡ddProÿÿÿÿÿÿ
  756. 9≈Q∞E¿™    ÿÿÿÿÿÿÿÿX¡ˆ ¡ddPro0¡˚ÿ]flµ
  757. ˜F§™
  758. Ê@(£KSendAck ˜
  759. 9≈"éD`ÑIêbZZ¡d
  760. dPro     ‘q≤]Ìd≤aÌdÌaÌ]≤a"†aï Ÿ¡ddPro
  761. ¡d
  762. dPro     ‘q^!eb!e!b!^b"∞bı Ÿ¡ddPro
  763. ¡ddProÿÿÿÿÿÿ    1ÜflU¡ˆ ¡ddPro(¡˚ÿflfi
  764. ÛÿX
  765. œ (å"MsgCmd, ¡ddPro(˚À(› bytesRec'd, ¡ddPro(áà+
  766. user data? ˜¡ddPro¡ddProÿÿÿÿÿÿ
  767. 9≈1-PDz¡ˆ ¡ddPro(¡˚ÿÊfl€
  768. ,ME}0`(6\Ack ¡ddPro(# (AQMsgPBlk ˜¡ddPro¡ˆ ¡ddPro(¡˚flïÿ¢
  769. P6b=(^Note:¡ddPro(Ÿ∏)  Each MsgPBlk can have a unique ¡ddPro(≥}(e&completion routine or they can share 
  770. ¡ddPro(I√+ !(ie num of Comp. Rtn's <= num of ¡ddPro(?ˇ+ MsgPBlk's, m<= n). ˜
  771. 9≈    ÿÿÿÿÿÿÿÿ"¢#F`Ü#õ<´Z¡d
  772. dPro     ‘qï+÷9ó9÷+ó+ï+ó9"ó.‡ Ÿ¡ddPro
  773. ¡ddProÿÿÿÿÿÿ    1”
  774. É<¡ˆ ¡ddPro(¡˚ÿEÿå
  775. ±Ê?Îà(»1..n ¡ddPro(©(Æ
  776. MsgPBlks ˜¡ddPro¡ddProÿÿÿÿÿÿ
  777. 9≈1”FÉ~¡ˆ ¡ddPro(¡˚ÿEÿ¸
  778. ±CÊ™°`(»H A non-busy ¡ddPro(É+ MsgPBlk ˜¡ddPro Ÿ ∞ÿDSET°ÿÿ.He /oÿÿÿÿÿÿ·tπ°√ÇΔY0°ÿÿ‚2K•߬•·tÀfi6ÿÿ*ÇΔY–aÿ ÿÿÿÿa–¡ddPro ≠ ‘ÿÿÿÿÿÿ
  779. –a     A    R    ÿÿÿÿÿÿÿÿHÿÿÿÿÿÿ    1$ê7`    ÿÿÿÿÿÿÿÿ8ÿÿÿÿÿÿ    1?êR`    ÿÿÿÿÿÿÿÿ8ÿÿÿÿÿÿ    1Zêm`    ÿÿÿÿÿÿÿÿ8ÿÿÿÿÿÿ    1uê√`    ÿÿÿÿÿÿÿÿ8ÿÿÿÿÿÿ    1˙ê¬`    ÿÿÿÿÿÿÿÿ8¡d
  780. dPro     ‘q)Û0ê-ê0Û-Û)Û-ê¡Øÿÿ•¡Öÿÿ• ◊¡´"-cx µ¡Öÿÿ• ◊ Ù¡Öÿÿ•¡Øÿÿ• ≤ Ù"-c"-l"-u"-~"-Ω"-Δ"-˙"-¢"-«"-´"-∏"-Æ"-Ï"-Ø¡Øÿÿ• ¿ Ù ◊ Ÿ¡ddPro
  781. ¡d
  782. dPro     ‘qDÛKêHêKÛHÛDÛHê¡Øÿÿ•¡Öÿÿ• ◊¡´"Hcx µ¡Öÿÿ• ◊ Ù¡Öÿÿ•¡Øÿÿ• ≤ Ù"Hc"Hl"Hu"H~"HΩ"HΔ"H˙"H¢"H«"H´"H∏"HÆ"HÏ"HØ¡Øÿÿ• ¿ Ù ◊ Ÿ¡ddPro
  783. ¡d
  784. dPro     ‘q_ÛfêcêfÛcÛ_Ûcê¡Øÿÿ•¡Öÿÿ• ◊¡´"ccx µ¡Öÿÿ• ◊ Ù¡Öÿÿ•¡Øÿÿ• ≤ Ù"cc"cl"cu"c~"cΩ"cΔ"c˙"c¢"c«"c´"c∏"cÆ"cÏ"cØ¡Øÿÿ• ¿ Ù ◊ Ÿ¡ddPro
  785. ¡d
  786. dPro     ‘qzÛ™ê~ê™Û~ÛzÛ~ê¡Øÿÿ•¡Öÿÿ• ◊¡´"~cx µ¡Öÿÿ• ◊ Ù¡Öÿÿ•¡Øÿÿ• ≤ Ù"~c"~l"~u"~~"~Ω"~Δ"~˙"~¢"~«"~´"~∏"~Æ"~Ï"~Ø¡Øÿÿ• ¿ Ù ◊ Ÿ¡ddPro
  787. ¡d
  788. dPro     ‘qıÛ¥ê¢ê¥Û¢ÛıÛ¢ê¡Øÿÿ•¡Öÿÿ• ◊¡´"¢cx µ¡Öÿÿ• ◊ Ù¡Öÿÿ•¡Øÿÿ• ≤ Ù"¢c"¢l"¢u"¢~"¢Ω"¢Δ"¢˙"¢¢"¢«"¢´"¢∏"¢Æ"¢Ï"¢Ø¡Øÿÿ• ¿ Ù ◊ Ÿ¡ddPro
  789. ÿÿÿÿÿÿ    1$67v    ÿÿÿÿÿÿÿÿ8ÿÿÿÿÿÿ    1?6Rv    ÿÿÿÿÿÿÿÿ8ÿÿÿÿÿÿ    1Z6mv    ÿÿÿÿÿÿÿÿ8ÿÿÿÿÿÿ    1u6√v    ÿÿÿÿÿÿÿÿ8ÿÿÿÿÿÿ    1˙6¬v    ÿÿÿÿÿÿÿÿ8¡ˆ ¡ddPro(¡˚ÿéÿö
  790. E, Palatino
  791. .ÿ–a–a+
  792.  Msg Selector ˜
  793. –a ¢"-6Ü"H6Ü"c6Ü"~6Ü"¢6Üÿÿÿÿÿÿ    1˙¬µ    ÿÿÿÿÿÿÿÿ8 ˝¡ˆ ¡ddPro0¡˚ÿû¿@2è•
  794. 
  795. ?@+lBMessaging System
  796. –aΔ!¡≈±!¡≈±!¡≈±øø•øø•øøÈÈXø›øø0xèÈÀ0<òÁ pøØ
  797. √√8Ëé)ïÖøø√øø
  798. ø
  799. øËé)ïÖøøHx80xèÈ0xèÈÈÈXø›øø•p8›•ø ˜ ˛¡ˆ ¡ddPro(¡˚ÿÎÿÀ
  800. (=6s
  801. (2@
  802. Msg type 1 ˜¡ˆ ¡ddPro(¡˚ÿ“ÿÀ
  803. C=Qs*
  804. Msg type 2 ˜¡ˆ ¡ddPro(¡˚ÿ˘ÿÀ
  805. ^=ls*
  806. Msg type 3 ˜¡ˆ ¡ddPro(¡˚ÿYÿÀ
  807. ˇ=«t*?
  808. Msg type n ˜¡ˆ ¡ddPro(¡˚ÿ}ÿÀ
  809. y=Ωs(∞@
  810. Msg type 4 ˜¡ˆ ¡ddPro(¡˚ÿÎÿ
  811. (ï6B(2òMsgCmd Base ID ˜¡ˆ ¡ddPro(¡˚ÿ“ÿ
  812. CïQR*MsgCmd Base ID + 1 ˜¡ˆ ¡ddPro(¡˚ÿ˘ÿ
  813. ^ïlR*MsgCmd Base ID + 2 ˜¡ˆ ¡ddPro(¡˚ÿ}ÿ
  814. yïΩR*MsgCmd Base ID + 3 ˜¡ˆ ¡ddPro(¡˚ÿYÿ
  815. ˇï«a*$MsgCmd Base ID + (n-1) ˜¡Øÿÿ•¡Öÿÿ• ◊¡´
  816. –a"—R µ¡Öÿÿ• ◊ Ù¡Öÿÿ•¡Øÿÿ• ≤ Ù ‘"—Q"‰Q Ÿ¡Øÿÿ• ¿ Ù ◊¡Øÿÿ•¡Öÿÿ• ◊¡´"—* µ¡Öÿÿ• ◊ Ù¡Öÿÿ•¡Øÿÿ• ≤ Ù ‘"—)"‰) Ÿ¡Øÿÿ• ¿ Ù ◊ Ÿ ∞ÿDSET(&ÿÿ.H/Imginÿÿÿÿÿÿ·uYF°ÿÿ√ΰÿÿV°ÿÿ˘    fi°ÿÿ
  817.   f°ÿÿ ¨î°ÿÿ0v°ÿÿ¸fl°ÿÿ@∫°ÿÿȰ    ÿÿPˆ°
  818. ÿÿذ ÿÿ` œ° ÿÿ è#.°
  819. ÿÿ#p%¶°ÿÿ%ø(>°ÿÿ(•*ưÿÿ+-N°ÿÿ-Δ/Ö°ÿÿG√° ÿÿϰÿÿW˘°ÿÿ    ß
  820.  °ÿÿ g ¨°ÿÿï0°ÿÿw¸°ÿÿÿ@°ÿÿΩȰÿÿP°    ÿÿ˜Ø°
  821. ÿÿ`° ÿÿ § è°
  822. ÿÿ#/#p°ÿÿ%·%ø°ÿÿ(?(•°ÿÿ*Ç+°ÿÿ-O-Δ°ÿÿ/◊0°ÿÿ6ÿÿ*ÇΔYDSET≠ÿÿ.Hh8ûdcÿÿÿÿÿÿ·tü…@‰A°ÿÿTÿÿ*…@‰°A†°A†°A†°A†°A†°A†°A†°A†°A†°A†°A°A†°A†°A †°A!†°A"†°A#†°A$†°A%†DSETT,@z·u·u·tà·tô°A·sÜAz$    "    
  823. "      n[ˇP[¥ΔWWl≤[¡‰
  824. {·tè{
  825. Technote 1076    ///          Release   1.2   © Apple Computer, Inc.      ///            ///          Page     of   19
  826. FNTMCUTSDSUM$ Tom MaremaaHDNISTYL@Ûÿÿ@STYL·t›·u˘·t‹·tÔ·tÄ·y¸·uΔ·u‰ÿÿt
  827. ÿÿÿÿ"ÿÿÿÿÿÿÿÿÿÿÿÿ
  828. 
  829. ÿÿ$ÿÿ&
  830. ÿÿ
  831. &ÿÿ
  832. ÿÿ$ÿÿ
  833. ÿÿÿÿÿÿÿÿÿÿ    ÿÿ ÿÿ        ÿÿ ÿÿÿÿ
  834.     ÿÿ 'ÿÿÿÿ ÿÿ
  835. ÿÿÿÿ ÿÿÿÿÿÿ
  836. ÿÿÿÿÿÿ    ÿÿ ÿÿ
  837. ÿÿ#ÿÿ ÿÿ$ÿÿ ÿÿ&ÿÿÿÿ
  838. ÿÿ*ÿÿÿÿ ÿÿ-ÿÿÿÿÿÿ%.‹ÿÿÿÿÿÿ/0..ÿÿÿÿ10.."ÿÿÿÿ40.."ÿÿÿÿ60.1"ÿÿÿÿ70.1"    ÿÿÿÿ80.1"
  839. ÿÿÿÿ90.1" ÿÿÿÿ:0.1" ÿÿÿÿ<0.1"
  840. ÿÿÿÿ=0./$ÿÿÿÿ >0./'ÿÿÿÿ!?0.4,ÿÿÿÿ"@0.4"ÿÿÿÿ%#B‹ÿÿÿÿÿÿ$C0BB-ÿÿ%F0BB"ÿÿ&K0BB"ÿÿÿÿ'M0BF,ÿÿ(N0BF"    ÿÿ)O0BF"
  841. ÿÿ*P0BF" ÿÿ+Q0BF" ÿÿ,R0BF"
  842. ÿÿÿÿ-S0BC.ÿÿÿÿ.T0BC/ÿÿÿÿ/U0BK0ÿÿ"0V0BK"ÿÿÿÿ%1W‹ÿÿÿÿÿÿ2X0WW1ÿÿÿÿ3Y0WW2ÿÿÿÿ4Z0WW2ÿÿÿÿ5[0WY3ÿÿÿÿ6\0WY4ÿÿÿÿ7]0WY4
  843. ÿÿÿÿ8^0WY4 ÿÿÿÿ9_0WY4 ÿÿÿÿ:`0WY4
  844. ÿÿÿÿ;a0WX5ÿÿÿÿ<b0WX5ÿÿÿÿ=c0WZ3ÿÿÿÿ>d0WZ4ÿÿÿÿ%?e‹ÿÿÿÿÿÿ@f0ee6ÿÿÿÿAg0ee"    ÿÿÿÿBh0ee"    ÿÿÿÿCi0eg7
  845. ÿÿÿÿDj0eg" ÿÿÿÿEk0eg"!
  846. ÿÿÿÿFm0eg""
  847. ÿÿÿÿGn0eg"#
  848. ÿÿÿÿHo0eg"$
  849. ÿÿÿÿIp0ef:% ÿÿÿÿJq0ef:& ÿÿÿÿKr0eh,'
  850. ÿÿÿÿLs0eh"(ÿÿÿÿ%Mt‹ÿÿÿÿ)ÿÿNu0tt;*ÿÿÿÿOv0tt"+ÿÿÿÿPw0tt", ÿÿÿÿQx0tv,-ÿÿÿÿRy0tv".ÿÿÿÿSz0tv"/ÿÿÿÿT{0tv"0ÿÿÿÿU|0tv"1ÿÿÿÿV}0tv"2ÿÿÿÿW~0tu<7ÿÿÿÿX0tu<8ÿÿÿÿY•0tw05ÿÿÿÿZ™0tw"6ÿÿÿÿ[≠‹ÿÿÿÿ)ÿÿ\∞0≠≠,*
  851. ÿÿO]≥0≠≠"+ÿÿÿÿ^∑0≠≠"3ÿÿÿÿ_∫0≠≥"-ÿÿÿÿ`Ω0≠≥"4ÿÿÿÿa√0≠≥"9ÿÿÿÿb≈0≠≥":ÿÿÿÿc…0≠≥";ÿÿÿÿd—0≠∞=7ÿÿÿÿe‘0≠∑,=ÿÿÿÿfŸ‹ÿÿÿÿ<ÿÿg⁄0ŸŸ>>ÿÿÿÿh∂0ŸŸ?ÿÿÿÿiΔ0Ÿ∂!ÿÿÿÿjŒ0Ÿ∂"ÿÿÿÿk‚0Ÿ∂#ÿÿÿÿl„0Ÿ∂$ÿÿÿÿm‰0Ÿ⁄?Bÿÿÿÿn0Ÿ⁄?CÿÿÿÿoˆØÿÿÿÿÿÿp˜8ˆˆÿÿÿÿq˘8ˆˆÿÿÿÿr˚8ˆˆÿÿÿÿs˝8ˆˆÿÿÿÿt˛8ˆˆÿÿÿÿuˇ8ˆˆÿÿÿÿvı8ˆˆÿÿÿÿwƒ8ˆˆÿÿÿÿx 8ˆˆÿÿÿÿy¡8ˆˆÿÿÿÿz¢8ˆˆÿÿÿÿ{£8ˆˆÿÿÿÿ|€Øÿÿÿÿ@ ÿÿ}¥8€€A!ÿÿÿÿ~œ8€€B#ÿÿÿÿ§8€€C%ÿÿÿÿ•¨8€€D,ÿÿÿÿ™©8€€D1ÿÿÿÿ≠ª8€€D2ÿÿÿÿ∞«8€€D3ÿÿÿÿ≥–8€€D4ÿÿÿÿ∑®8€€D5ÿÿÿÿ∫¯8€€D6ÿÿÿÿ Ω°Øÿÿÿÿ7ÿÿ√±8°°8ÿÿÿÿ≈”8°°9ÿÿÿÿ…“8°°:ÿÿÿÿ—´8°°;ÿÿÿÿ‘µ8°°<ÿÿÿÿŸ    )ÿÿÿÿ⁄Ë     
  852. ÿÿÿÿ∂ÉÿÿËÿÿÿÿΔJ    ÿÿ *ÿÿÿÿŒ†ÿÿJKÿÿ    ‚’     ÿÿÿÿ„ÿÿ#)ÿÿÿÿ‰ÿÿ’ÿÿÿÿß     Aÿÿÿÿˆß=ÿÿÿÿ˜      ÿÿÿÿ˘ÿÿ ÿÿÿÿ˙"    ÿÿ ÿÿÿÿ˚¿ÿÿ"JÿÿÿÿS˝,    ÿÿ ÿÿÿÿ˛¶ÿÿ,+ÿÿÿÿˇ·ÿÿ,)+ÿÿÿÿ
  853. ı¸    ÿÿ -ÿÿÿÿƒºÿÿ¸0ÿÿÿÿ »ÿÿ,*+ÿÿÿÿ¡Âÿÿ¸9 ÿÿÿÿ¢Äÿÿ,ÿÿÿÿ£Åÿÿ¸90ÿÿÿÿ€Æÿÿ,F+ÿÿÿÿ¥Çÿÿ,G+ÿÿÿÿ
  854. œÈ    ÿÿ >ÿÿÿÿ§ÊÿÿÈ?ÿÿÿÿQ¨Í    ÿÿ @ÿÿÿÿ
  855. ©ÏÿÿÍHBÿÿÿÿ"ªÑ    ÿÿ Cÿÿ¢«ÓÿÿÑÿÿÿÿ¬ÚÿÿÑGDÿÿÿÿ$–ÛÿÿÑDÿÿÿÿ®fiÿÿÿÿÿÿ¯àÿÿÑ)Dÿÿÿÿ°á    ÿÿ Eÿÿÿÿ±äÿÿáHÿÿÿÿ”åÿÿÑFDÿÿÿÿ“æÿÿÑ*Dÿÿÿÿ    ´é    ÿÿ Iÿÿ¡µëÿÿé9 ÿÿÿÿ¶›ÿÿÑGÿÿÿÿ·óÿÿÑ)ÿÿ«¸ÁÿÿÑÿÿÿÿ’ÿÿ,+ÿÿÿÿº,ÿÿº»Íÿÿ»π!Ñÿÿÿÿ∏2    ÿÿ ÿÿÿÿ≤Lÿÿ2ÿÿÿÿ¿+    ÿÿ (ÿÿÿÿÀAÿÿ+.ÿÿÿÿÁ(    ÿÿ     ÿÿÿÿÂIÿÿé ÿÿÿÿ
  856. à   ÿÿ /ÿÿÿÿÄÿÿFÿÿÿÿÅ'ÿÿÿÿÿÿÆG    ÿÿ LÿÿÿÿÇHÿÿG MÿÿÿÿÈ0    ÿÿ Nÿÿ·ÉDÿÿ0)ÿÿ¸Êlÿÿ0ÿÿÿÿË˙ÿÿ  ÿÿÿÿ̬ÿÿ(ÿÿÿÿÍπÿÿ(&ÿÿÿÿÎ∏ ¸+ÿÿÿÿÏ≤,8ÿÿ‹À$,EÿÿÿÿÑÃÑIÿÿÏÒÌÑ8ÿÿÎÓΠé+ÿÿ‹Ô‹$2EÿÿÿÿÕ
  857. ÿÿ)ÿÿÿÿÖ ÿÿ    )ÿÿÿÿ◊ÿÿÑ
  858. DÿÿÿÿØÿÿÑDÿÿÿÿÙ
  859. ÿÿ+GÿÿÿÿÚEÿÿ2Oÿÿ®ÅÿÿHASH‘
  860. $Ú àù¡àú ô◊‘Môؑ[ÑÛÔ#ÑÛÔ1à"ÔÎá´fiãã%8◊fãµÕá?êä
  861. ëå
  862. &Â
  863. &\µ-& ÇP& ÑQ&≤R&ÊR&¶R&!É&Æœ,Œ”& Èöb ,Δ_b
  864. ,√Q≈v…˝—À‘,pQqvr˝sÀtåu
  865. v/wTxyyızÃ{,8}QI~v4˝5•À5™å5≠    
  866. 5∞    /5≥    T5∑    y5∫ ‹Ä A‹◊ A‹Ú B‹Ø B‹– B‹¬ B‹!¯ B‹2“ G‹” N‹⁄© bÏÄ´ ∑ÏÄà ¢Ï̪ ©ÏÄ∏ )Į̈KvV%()*+,00!OIPJCU ø- .    07    18    29    3:CdJWKX    (3
  867. G/    5'%x®3öÅy·=y˝;Ù?<Ù    H>ùù&ùB5ù    $4ù    36‡J@‡>‡ ENÿ>\2ï$h-E.F/G0HFK`C/S0T1U2V0ZJY&
  868. Ô& Ò&D.L&Ó    &π
  869. "A
  870. #B
  871. $]
  872. %^klij*mG& ∂O&⁄P&‰P&
  873. ‚…”nΔ& ˘Δ&ËŒ&    ˜ûHe‡/R‡9b‡:c‡1_‡7`‡8a‡DQfl0g'P&ˆA,&ÀK‹ÙKB‹±K∫Ï¿K€ÏʰL: QM6hƒM6hO£M~h˛M~h’M~h¥M~hˇM~h% M∞h€Mıg·ıMµgï§Mfig¿˝N!g¡œQ& „Q&
  874. ŸQ.?ÖQ._Õf&˚f&Ìf&Ífw&˙f|&Áf¸eg|h“çmh’ÑÚj–◊alq”ºr§élr”◊at“◊ÅΩz«áoz¶ÕÄ}Bod}©ÓÖofiJ 
  875. CHAR·uÿÿÿÿ ÿÿ ÿÿÿú    ÿÿ6ÿÿ"    ÿÿÿúÿÿÿû
  876. ÿÿ•ÿÿÿÿÿÿ
  877. ÿòÓÿÿ6ÿß"    ÿÿÿfl 
  878. ÿÿ ÿÿÿÿÿfl
  879. ÿÿÿúÿÿÿûÿÿÿÿ
  880. ÿÿ ÿóÿÿ&ÿß
  881. ÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿ 'ÿØ
  882. ÿÿÿû
  883. ÿé#"ÿ† ÿÿÿ÷ àÿÿÿÿ
  884. ÿÿ"
  885. ÿÿÿÿÿÿ à!ÿÿÿÿ ÿÿàÿÿÿÿ%ÿÿÿÿ>ÿÿ"    à(
  886. ÿÿÿÿ    '
  887. (ÿÿÿÿ>ÿ◊"    àÿÿÿÿÿÿ%
  888. ÿÿÿÿÿÿ ÿÿÿÿÿÿ
  889. ÿÿ&ÿÿ
  890. ÿ÷ÿÿ
  891. ÿÿ     -
  892.     ÿÿ
  893.     ÿÿ
  894.     ÿÿ.    ÿÿ
  895.     ÿÿ
  896. 2
  897. 
  898.     1/    ÿÿ*
  899. '2
  900. ÿ÷ÿÿFÿÿ6/
  901. ÿÿ        ;        ,
  902. ÿÿ>ÿÿ&    ÿÿ&ÿÿ  ÿÿ&
  903. @&    ÿ÷ ÿÿÿÿ
  904. ÿÿÿÿ ÿÿÿÿ    Eÿfl $.ÿÿHASH?0C1D4AEB ≥""=3$:5;:D7.)/*3    4    )<    *0     I
  905. 8
  906.     @        `à 
  907.      
  908. + &G )1*[9Ó    
  909. H    FfD@
  910. CELL·tØ!ÿÿÿÿÿ]ÿÿÿ"ÿÿÿÿÿÿü
  911. ÿÿÿÿø
  912. ÿÿøÿÿÿÿÿÿÿÿÿÿ    ÿÿü
  913. ÿÿü
  914. ÿÿø
  915. ÿÿø
  916. ÿÿü
  917. ÿÿÿÿü
  918. ÿÿü
  919. ÿÿøÿÿøøÿÿÿÿÿÿÿÿx≥
  920. ÿÿØ$ ÿÿx• ÿÿØ 
  921. ÿÿÿÿÿÿÿÿÿÿ    ÿÿø
  922. ÿÿø ÿÿ ÿÿ
  923. ÿÿÿÿøÿÿÿÿûÿÿøÿÿøÿÿÿÿÿÿÿÿ    ÿÿÿÿøÿÿÿ ÿÿÿ
  924. ÿÿü
  925. ÿÿü ÿÿøÿÿøÿÿø    ÿÿÿÿø ÿÿø
  926. ÿÿAÿÿÿÿø
  927. ÿÿÿÿÿÿø ÿÿ(Ó
  928. ÿÿ√s ˆAÿÿHASHÿ    
  929.       
  930. 
  931. % &78)xŸx∂Ø1Ø3øøø    ø
  932. ø
  933. *ü ü ?     !
  934. " # $'(
  935. /012
  936. 56<+3*èB…‘Cú>ú
  937. .ú-ú=ú4ú9ú:ú;‡    , ÿÿ
  938. GRPH·tÈàÿÿÿÿÿ[ÿÿÿBÿÿÿÿÎÿÿ
  939. ÿÿÎÿÿ
  940. ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿìÿÿn⁄ÿÿHASH
  941. 
  942. Ò    Î 
  943. o í!ÖPÿÿl
  944. RULR·vxÿÿÿÿÿ`¿Hé4@¢*à!?Ω4zÔ€=≈(=Sπ=SÌ=mè=mü=WL=møÿÿh7GZ.l.~.Δ.¢.´.Æ.Ô€=≈(=Sπ=SÌ=mè=mü=WL=møÿÿ\ÿÿfl@HÿÿÿGÿÿ $ÿÿÿHÿÿÿ@Hÿÿi÷ÂGdÿÿ÷?ÿÿ $ÿÿÿÿÿÿªB<ÿÿ     $ÿÿÿÿÿ?ÿÿ$ÿÿHÿÿi÷ÂBdÿÿlÿÿΔÿÿÿHÿÿ´ÿÿØÿÿüÿÿ ÿÿDÿÿ    hÿÿÿÂGdÿÿ
  945. ‘ÿÿ °ÿÿÿÿ$ÿÿÿÿÿHÿÿ‡@ÿÿlÿÿ÷Hÿÿi÷ªB<ÿÿj5@"Z.l.~.Δ.¢.´.Æ.Ô€=≈(=Sπ=SÌ=mè=mü=WL=møÿÿÿ@ÿÿi÷ZBÿÿÿHé4@¢*à!?Ω4zÔ€=≈(=Sπ=SÌ=mè=mü=WL=møÿÿΔÿÿh·é4@¢*à!?Ω4zÔ€=≈(=Sπ=SÌ=mè=mü=WL=møÿÿÿ@"ÿÿh7#Z.l.~.Δ.¢.´.Æ.Ô€=≈(=Sπ=SÌ=mè=mü=WL=møÿÿÿé4@¢*à!?Ω4zÔ€=≈(=Sπ=SÌ=mè=mü=WL=møÿÿ´ÿÿØÿÿüÿÿ ÿÿDÿÿ    hÿÿÿÿ$ÿÿHÿÿlÿÿΔÿÿ´ÿÿi÷jBÿÿl“ÿî~é4@¢*à!?Ω4zÔ€=≈(=Sπ=SÌ=mè=mü=WL=møÿÿÿÿî~é4@¢*à!?Ω4zÔ€=≈(=Sπ=SÌ=mè=mü=WL=møÿÿà?HZ.l.~.Δ.¢.´.Æ.Ô€=≈(=Sπ=SÌ=mè=mü=WL=møÿÿibBN.*à!i≤p¥SägÚ°g¥lg¥|g¿˘g¿¬g¨üg¿¨ÿÿÿHZ.l.~.Δ.¢.´.Æ.Ô€=≈(=Sπ=SÌ=mè=mü=WL=møÿÿ`?HZ.l.~.Δ.¢.´.Æ.Ô€=≈(=Sπ=SÌ=mè=mü=WL=møÿÿHZ.l.~.Δ.¢.´.Æ.Ô€=≈(=Sπ=SÌ=mè=mü=WL=møÿÿb=@HZ.l.~.Δ.¢.´.Æ.Ô€=≈(=Sπ=SÌ=mè=mü=WL=møÿÿ#Z.l.~.Δ.¢.´.Æ.Ô€=≈(=Sπ=SÌ=mè=mü=WL=møÿÿ@"Z.l.~.Δ.¢.´.Æ.Ô€=≈(=Sπ=SÌ=mè=mü=WL=møÿÿ@HZ.l.~.Δ.¢.´.Æ.Ô€=≈(=Sπ=SÌ=mè=mü=WL=møÿÿh7Z.l.~.Δ.¢.´.Æ.Ô€=≈(=Sπ=SÌ=mè=mü=WL=møÿÿÿÂBdÿÿÿZBÿÿh÷#ÿÿÿ#ÿÿ`ÿHÿÿGZ.l.~.Δ.¢.´.Æ.Ô€=≈(=Sπ=SÌ=mè=mü=WL=mø›PÿÿHASH %MIJŸùLıKªNî>
  946. ù*W=ù'7,80Q9v:˝;À<0 ,Qv˝Àå 
  947. /TyıÃ,!Q#v%˝,À1å2    
  948. 3    /4    T5    y6
  949. ¬F
  950. 0
  951. 9¬O
  952. :¬D
  953. AªB
  954. Z«’I
  955. }«’/
  956. ˚«ÁC
  957. ¡«’ !«Á@CRKAÿ?ÿG÷
  958. HÿP÷&√ÿ≈flÿ"ù=@$.J¬GJ:¬HJ~«·(J˛«¿EL.Cô0LvCô+LˆC¬-L–Câ?LÖC´MCˆ>Pÿ)P‡$eJe eoùetù    &LKUP    ÕÖ˜Ù◊’ ‰„ØºÃ˘%
  959. Ä »Ÿ
  960. π˙)ÅÁ3¿˝È∏5;Ò !"À#$ÉÚ%ÆÇÂΔ&≤'()*+,-./0123456789:;<=>?@ABCDEÊFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqËrstuvwxyz{|}~•™≠∞Ì≥∑∫Ω√≈…—‘˛ˇı‚ƒ ÍÎÏ˚‹¸¡Ñ¢£€¥œ∂§⁄Ò¨Ó©ÔªÔ«ÕÖ◊ØÙܬ–⌮¯°ãç±”“èê´ìµíîïñ¶òô·õö÷øùúûü‡flÿÿÿˆ¸ÿÿ$NAMEDefault
  961. Default SSHeaderBodyFooterFootnoteFootnote Index Heading2.H2 HeadingH2.H2Code.CV  Heading1.H1#Italic$ HeadingH3.H3&Bullet*    Checklist-Number.ClassicB Blue Gray 1W Blue Gray 2eColorfult
  962. 3D Table 1≠
  963. 3D Table 2Ÿ
  964. AccountingˆHarvard€Legal°Diamond0DFNTM    HelveticaGenevaPalatino:H
  965. Letter GothicChicago
  966. Zapf DingbatsÿÿSymbolCourierETBL@FNTMîNCUTSîVDSUMî^HDNIî…STYLî‰ETBLH ÿfl‡üûúùø›ñòóôõö÷
  967.